package cn.mrcode.wxsdk.core.dialogue.common.accessToken.lifeCycle.distributed.strategy.master_old;

import cn.mrcode.wxsdk.core.dialogue.common.LogUtil;
import cn.mrcode.wxsdk.core.dialogue.common.PublicAccount;
import cn.mrcode.wxsdk.core.dialogue.common.accessToken.AccessTokenApi;
import cn.mrcode.wxsdk.core.dialogue.common.distributed.ZkDistributedSingleNodeExecutor;
import cn.mrcode.wxsdk.core.dialogue.common.exception.ReqException;
import cn.mrcode.wxsdk.core.dialogue.common.exception.WxException;
import cn.mrcode.wxsdk.core.dialogue.common.log.LogTemplateUtil;
import cn.mrcode.wxsdk.core.dialogue.protocol.base.AccessTokenInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * zk token 实现类
 * @author zhuqiang
 * @version V1.0
 * @date 2015/9/24 9:53
 */
@Deprecated
public class ZkAccessToken extends ZkDistributedSingleNodeExecutor {
    private static Logger log = LoggerFactory.getLogger(ZkAccessToken.class);
    private ConcurrentHashMap<String, AccessTokenInfo> accessTokenMap; // 使用该引用更新token到本地项目中
    private HashMap<String, PublicAccount> accountMap; //公众号map

    private ConcurrentHashMap<String, AccessTokenInfo> taskMap;  //用于任务中 更新的 token 列表

    /**
     * 构建 执行器
     *
     * @param sessionTimeout 链接超时毫秒
     * @param zkServiceList  zk服务器地址，逗号隔开
     * @param rootPath       根目录 路径（不存在将被自动创建，最好存在） 例如： /wxBaseToken
     * @param accessTokenMap  使用该引用更新token到本地项目中
     */
    public ZkAccessToken(int sessionTimeout, String zkServiceList, String rootPath,ConcurrentHashMap<String, AccessTokenInfo> accessTokenMap,HashMap<String, PublicAccount> accountMap){
        super(sessionTimeout, zkServiceList, rootPath,accessTokenMap);
        this.accountMap = accountMap;
    }

    @Override
    protected void executor(ZkDistributedSingleNodeExecutor zkDistributedSingleNodeExecutor,String data) {
        //数据不为空，那么就不是第一次，把已经有的数据 添加进任务列表
        if(StringUtils.isNotBlank(data)){
            if(!data.contains("true")){
                List<AccessTokenInfo> list = JSON.parseArray(data, AccessTokenInfo.class);
                for (AccessTokenInfo ati : list) {
                    String appID = ati.getAppID();
                    if(accountMap.containsKey(appID)){
                        taskMap.put(appID,ati);
                    }
                }
            }
        }
        initAccessToken(); // 检查是否有新增 公众号，需要去把列表中的开发者账户，token拿到
        new Thread(new AccessTokenDistributedTask(zkDistributedSingleNodeExecutor,taskMap)).start();
        log.info(LogTemplateUtil.svMsg("接管执行更新任务","%s,id=%s,data=%s",getRootPath(),getThisPath(),data));
    }

    @Override
    protected void firstRefresh(String data,Object obj) {
        log.info(LogTemplateUtil.svMsg("首次获得数据","%s,id=%s,data=%s",getRootPath(),getThisPath()+"",data));
        accessTokenMap = (ConcurrentHashMap<String, AccessTokenInfo>)obj;
        taskMap = new ConcurrentHashMap<String, AccessTokenInfo>();
        this.refresh(data);
    }

    @Override
    protected void refresh(String data) {
        final String apiName = "刷新数据";
        taskMap.clear();
        if(StringUtils.isNotBlank(data)){
            if(!data.contains("true")) {
                List<AccessTokenInfo> list = JSON.parseArray(data, AccessTokenInfo.class);
                for (AccessTokenInfo ati : list) {
                    String appID = ati.getAppID();
                    accessTokenMap.put(appID, ati);
                    taskMap.put(appID,ati);
                }
                log.info(LogTemplateUtil.svMsg(apiName,"%s;id=%s;将新数据已刷入本地缓存=%s",getRootPath(),getThisPath(), JSONObject.toJSONString(list)));
            }
        }
    }

    /**
     * 初始化 task 任务数据
     */
    private void initAccessToken() {
        for (Map.Entry<String,PublicAccount> ent:accountMap.entrySet()){
            String appId = ent.getKey();
            PublicAccount pa = ent.getValue();
            if(!taskMap.containsKey(appId)){ //如果不包含则需要 获取token
                AccessTokenInfo accessTokenInfo = null;
                try {
                    accessTokenInfo = AccessTokenApi.getAccessTokenInfo(appId, pa.getAppSecret());
                } catch (ReqException e) {
                    log.error(LogUtil.fromateLog(e));
                    throw new RuntimeException(e);
                } catch (WxException e) {
                    log.error(LogUtil.fromateLog(e));
                    throw new RuntimeException(e);
                }
                taskMap.put(appId,accessTokenInfo);
            }
        }
        // 把获取的数据 上传一份先
        Collection<AccessTokenInfo> values = taskMap.values();
        List<AccessTokenInfo> data = new ArrayList<AccessTokenInfo>(values);
        this.writeData(JSON.toJSONString(data));
    }
}
